package com.zhongda.cloud.config;

import org.springframework.core.env.Environment;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore;
import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore;

import com.zhongda.cloud.service.security.OAuthUserDetailsService;

import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;

/***
 * 
 * 
 * 项目名称：auth-service 
 * 类名称：OAuth2ServerConfig 
 * 类描述： OAuth2授权 
 * 创建人：zxf
 * 创建时间：2017年8月18日 上午11:21:31 
 * 修改人：Administrator 
 * 修改时间：2017年8月18日 上午11:21:31 
 * 修改备注：
 * 
 * @version
 *
 */
@Configuration
public class OAuth2ServerConfig {

	@Configuration
	@EnableAuthorizationServer
	protected static class OAuth2AuthorizationConfig extends AuthorizationServerConfigurerAdapter {

		private TokenStore tokenStore = new InMemoryTokenStore();

		//authenticationManager：认证管理器，当你选择了资源所有者密码（password）授权类型的时候，请设置这个属性注入一个 AuthenticationManager 对象。
		@Autowired
		@Qualifier("authenticationManagerBean")
		private AuthenticationManager authenticationManager;

		 @Autowired
		 private RedisConnectionFactory redisConnectionFactory;


		 @Bean
		 public RedisTokenStore tokenStore() {
		     return new RedisTokenStore(redisConnectionFactory);
		 }

		
		//userDetailsService：如果啊，你设置了这个属性的话，那说明你有一个自己的 UserDetailsService 接口的实现，或者你可以把这个东西设置到全局域上面去（例如 GlobalAuthenticationManagerConfigurer 这个配置对象），当你设置了这个
		//之后，那么 "refresh_token" 即刷新令牌授权类型模式的流程中就会包含一个检查，用来确保这个账号是否仍然有效，假如说你禁用了这个账户的话。
		@Autowired
		private OAuthUserDetailsService oAuthUserDetailsService;
		
		@Autowired
		private Environment env;

		@Override 
		public void configure(ClientDetailsServiceConfigurer clients) throws Exception {

			// TODO persist clients details

			// @formatter:off
			clients.inMemory()
				   .withClient("browser")
				   .authorizedGrantTypes("refresh_token", "password")
				   .scopes("ui")
			.and()
				   .withClient("account-service")
				   //.secret(env.getProperty("ACCOUNT_SERVICE_PASSWORD"))
				   .secret("root")
				   .authorizedGrantTypes("client_credentials", "refresh_token")
				   .scopes("server")
		    .and()
				   .withClient("statistics-service")
				   .secret("root")
				   .authorizedGrantTypes("client_credentials", "refresh_token")
				   .scopes("server")
		    .and()
				   .withClient("notification-service")
				   .secret("root")
				   .authorizedGrantTypes("client_credentials", "refresh_token")
				   .scopes("server")
			.and()
			   		.withClient("sample-service")
			   		.secret("root")
			   		.authorizedGrantTypes("client_credentials", "refresh_token")
			   		.scopes("server");
			// @formatter:on
		}

		//AuthorizationServerEndpointsConfigurer 这个配置对象(AuthorizationServerConfigurer 的一个回调配置项，见上的概述) 有一个叫做 pathMapping() 的方法用来配置端点URL链接，它有两个参数：
		//第一个参数：String 类型的，这个端点URL的默认链接。
		//第二个参数：String 类型的，你要进行替代的URL链
		@Override //来配置令牌端点(Token Endpoint)的安全约束.
		public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
			endpoints.tokenStore(tokenStore).authenticationManager(authenticationManager)
			 .userDetailsService(oAuthUserDetailsService);
		}

		@Override //用来配置授权（authorization）以及令牌（token）的访问端点和令牌服务(token services)
		public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
			oauthServer.tokenKeyAccess("permitAll()").checkTokenAccess("isAuthenticated()");
		}
	}
}
